#ifndef __HSMATH_ELEMENT_1D__
#define __HSMATH_ELEMENT_1D__
#include <iostream>
#include <fstream>
/**
 * @file   Element_1D.h
 * @author Shuang Hu <hsmath@ubuntu>
 * @date   Sun Mar 21 23:46:16 2021
 * 
 * @brief  Copy from wang_heyu and make a debug work
 * 
 * 
 */
class Point_1
{
private:
    double *coord;
    int index;
public:
    Point_1();
    Point_1(double _x);
    Point_1(double _x, int _i);
    ~Point_1();
    Point_1(const Point_1 &_p);
    int get_index() const; 
    void set_index(int _i);
    double get_coord() const;
    void set_coord(double _c);
    const Point_1& operator=(const Point_1 &_p);
    friend std::ostream& operator<<(std::ostream &_os, const Point_1 &_p);
    friend Point_1 operator+(const Point_1 &_p1, const Point_1 &_p2);
};

std::ostream& operator<<(std::ostream &_os, const Point_1 &_p);

Point_1 operator+(const Point_1 &_p1, const Point_1 &_p2);

class Interval
{
private:
    Point_1 a;//Left side
    Point_1 b;//Right side
public:
    Interval();
    Interval(double _a, double _b);
    Interval(const Point_1 &_a, const Point_1 &_b);
    ~Interval();
    void set_a(const Point_1 &_p);
    void set_b(const Point_1 &_p);
    const Point_1& get_a();
    const Point_1& get_b();
    friend std::ostream& operator<<(std::ostream &_os, const Interval &_i);
};

std::ostream& operator<<(std::ostream& _os, const Interval& _i);

class Mesh_1
{
private:
    Interval *interval;
    int n_grids;
    Interval *elements;
public:
    Mesh_1(const Point_1 *_a, int _n_nodes);
    ~Mesh_1();
    const Interval& get_interval();
    int get_n_grids();
    int get_n_nodes();
    const Interval& get_element(int _i);
};

class Element_1_1
{
private:
    Point_1 a;
    Point_1 b;
    int n_dofs = 2;
public:
    Element_1_1();
    Element_1_1(const Point_1& _a, const Point_1& _b);
    ~Element_1_1();
    void set_a(const Point_1& _a);
    void set_b(const Point_1& _b);
    double phi_a(double _x);
    double phi_b(double _x);
};

class Quad_Info
{
private:
    int accuracy;
    int n_q_points;
    double **q_info;
public:
    Quad_Info();
    void set(int _acc, int _n_q_pnts, double **_q_info);
    int get_accuracy() const;
    int get_n_q_points() const;
    const double* get_pAw(int _idx) const;
    ~Quad_Info();
};

class Quad
{
private:
    int n_table;
    Quad_Info *quad_info;
public:
    Quad();
    ~Quad();
    void load_data(const char _file[]);
    int get_n_table() const;
    const Quad_Info& get_quad_info(int _acc) const;
    void list() const;
    double g2l(double _a, double _b, double _x) const;
    double l2g(double _a, double _b, double _t) const;
    double Jacobian(double _a, double _b) const;
};


#else
// DO NOTHING.
#endif
